import java.util.HashMap;
import java.util.Map;

public class 享元模式 {
    public static void main(String[] args) {
        // 创建多个单车对象，位置不同，但共享相同的品牌信息
        Bike bike1 = new Bike(40.748817, -73.985428, "Ofo", "Yellow");
        Bike bike2 = new Bike(34.052235, -118.243683, "Mobike", "Orange");
        Bike bike3 = new Bike(37.774929, -122.419418, "Ofo", "Yellow");
        Bike bike4 = new Bike(51.507351, -0.127758, "Ofo", "Yellow");

        // 显示单车信息
        bike1.display();
        bike2.display();
        bike3.display();
        bike4.display();

        // 输出品牌缓存的大小（共享的品牌对象数量）
        System.out.println("\nBike brands in cache: " + BikeFactory.getCacheSize());
    }
}
// 享元类：表示共享单车的品牌信息
 class BikeBrand {
    private String brandName;
    private String color;

    // 构造方法：品牌名称和颜色
    public BikeBrand(String brandName, String color) {
        this.brandName = brandName;
        this.color = color;
    }

    // 获取品牌名称
    public String getBrandName() {
        return brandName;
    }

    // 获取单车颜色
    public String getColor() {
        return color;
    }

    // 显示品牌信息
    public void display() {
        System.out.println("Bike Brand: " + brandName + ", Color: " + color);
    }
}
//享元工厂类  负责管理共享单车的品牌对象。
// 它会缓存所有已创建的品牌对象，以确保相同品牌和颜色的单车只创建一次。
// 享元工厂：管理共享单车的品牌对象
 class BikeFactory {
    private static Map<String, BikeBrand> bikeBrandCache = new HashMap<>();

    // 获取单车品牌对象，若品牌对象已存在则返回缓存中的对象，否则创建新的对象
    public static BikeBrand getBikeBrand(String brandName, String color) {
        // 创建一个品牌的唯一标识符
        String key = brandName + "-" + color;

        // 如果缓存中不存在该品牌对象，则创建并缓存
        if (!bikeBrandCache.containsKey(key)) {
            bikeBrandCache.put(key, new BikeBrand(brandName, color));
        }

        // 返回缓存中的品牌对象
        return bikeBrandCache.get(key);
    }

    // 获取品牌对象缓存的数量
    public static int getCacheSize() {
        return bikeBrandCache.size();
    }
}
//单车类 它包含了唯一的属性（如位置、租赁状态）和一个共享的品牌对象。每辆单车将通过享元工厂获取共享的品牌对象。
// 单车类：表示一辆共享单车
 class Bike {
    private double latitude;
    private double longitude;
    private BikeBrand bikeBrand; // 单车共享品牌

    // 构造方法：单车位置、品牌名称、颜色
    public Bike(double latitude, double longitude, String brandName, String color) {
        this.latitude = latitude;
        this.longitude = longitude;
        // 从享元工厂获取共享品牌对象
        this.bikeBrand = BikeFactory.getBikeBrand(brandName, color);
    }

    // 显示单车信息
    public void display() {
        System.out.print("Bike at [" + latitude + ", " + longitude + "] | ");
        bikeBrand.display();
    }
}